import {
  InterceptorHandlerType,
  InterceptorOptions,
  InterceptorType,
  RequestInterceptor,
  ResponseInterceptor,
} from "../types/interceptor";

export class CenoInterceptor {
  private readonly handlers = {
    request: [] as RequestInterceptor[],
    response: [] as ResponseInterceptor[]
  };

  use(interceptors: InterceptorOptions): void {
    Object.entries(interceptors).forEach(([type, interceptor]) => {
      if (interceptor) {
        const handlers = Array.isArray(interceptor) ? interceptor : [interceptor];
        this.handlers[type as keyof typeof this.handlers].push(...handlers);
      }
    });
  }

  snapshot(): InterceptorOptions {
    return {
      request: [...this.handlers.request],
      response: [...this.handlers.response]
    }
  }

  async execute<T extends 'request' | 'response'>(
    type: T,
    value: InterceptorType<T>,
    tempInterceptors?: InterceptorHandlerType<T>
  ): Promise<InterceptorType<T>> {
    const registeredHandlers = this.handlers[type] as InterceptorHandlerType<T>[]
    const tempHandlers = tempInterceptors 
        ? (Array.isArray(tempInterceptors) ? tempInterceptors : [tempInterceptors])
        : []

    let result = value
    
    for (const handler of [...registeredHandlers, ...tempHandlers]) {
        try {
            result = handler.onFulfilled ? await handler.onFulfilled(result) : result
        } catch (error) {
            if (handler.onRejected) {
                result = await handler.onRejected(error)
            } else {
                throw error
            }
        }
    }
    
    return result
  }
}
